﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using Zipun.VkOnlineMusic.Api.Domain;
using Zipun.VkOnlineMusic.View.WinForms.Properties;

namespace Zipun.VkOnlineMusic.View.WinForms.Controls
{
    public partial class AudioList : UserControl
    {
        private int _nowPlayingRowIndex;

        public event EventHandler<AudioChangedByUserEventArgs> AudioChangedByUser;

        private List<VkAudio> _audios;
        [Browsable(false)]
        public void SetAudios(List<VkAudio> value)
        {
            if (Site != null && Site.DesignMode)
                return;
            _audios = value;
            if (audioDataGridView == null)
                return;
            audioDataGridView.DataSource = _audios;
            audioScrollBar.SliderSize = (double)audioDataGridView.DisplayedRowCount(true) / audioDataGridView.Rows.Count;
        }

        public VkAudio SelectedItem
        {
            get
            {
                if (audioDataGridView.SelectedRows.Count < 1)
                    return null;
                return audioDataGridView.SelectedRows[0].DataBoundItem as VkAudio;
            }
        }

        public void SetNowPlaying(VkAudio value)
        {
            if (_nowPlayingRowIndex >= 0)
                audioDataGridView.Rows[_nowPlayingRowIndex].DefaultCellStyle = new DataGridViewCellStyle();
            if (value == null)
            {
                _nowPlayingRowIndex = -1;
                return;
            }
            _nowPlayingRowIndex = getRowIndexByBoundedItem(audioDataGridView, value);
            if (_nowPlayingRowIndex == -1)
                return;
            var nowPlayedRow = audioDataGridView.Rows[_nowPlayingRowIndex];
            var style = nowPlayedRow.DefaultCellStyle;
            style.Font = new Font(audioDataGridView.DefaultCellStyle.Font, FontStyle.Bold);
            style.ForeColor = Color.WhiteSmoke;
            if (nowPlayedRow.Displayed &&
                _nowPlayingRowIndex - audioDataGridView.DisplayedRowCount(false) + 1 <=
                audioDataGridView.FirstDisplayedScrollingRowIndex)
            {
                return;
            }
            // We scroll up
            if (_nowPlayingRowIndex <= audioDataGridView.FirstDisplayedScrollingRowIndex)
            {
                // first row = played row
                audioDataGridView.FirstDisplayedScrollingRowIndex = _nowPlayingRowIndex;
                autosetScrollbarPosition();
                return;
            }
            // We scroll down - last row = palyed row
            //
            var newFirstDisplayedRow = _nowPlayingRowIndex - audioDataGridView.DisplayedRowCount(true) + 2;
            audioDataGridView.FirstDisplayedScrollingRowIndex = newFirstDisplayedRow > 0 ? newFirstDisplayedRow : 0;
            autosetScrollbarPosition();
        }

        public AudioList()
        {
            _audios = new List<VkAudio>();
            InitializeComponent();
            _nowPlayingRowIndex = -1;
            audioDataGridView.MouseWheel += audioDataGridView_MouseWheel;
            audioScrollBar.PositionChanged += audioScrollBar_PositionChanged;
        }

        void audioScrollBar_PositionChanged(object sender, EventArgs e)
        {
            var scroll = sender as VomVScrollBar;
            if (scroll == null)
                return;
            if (audioDataGridView.Rows.Count < 1)
                return;
            audioDataGridView.FirstDisplayedScrollingRowIndex = (int)(scroll.Position * (audioDataGridView.Rows.Count - 1));
        }

        private void audioDataGridView_MouseWheel(object sender, MouseEventArgs e)
        {
            var newPosition = audioDataGridView.FirstDisplayedScrollingRowIndex - e.Delta / 40;
            if (newPosition < 0)
                newPosition = 0;
            if (newPosition + audioDataGridView.DisplayedRowCount(false) > audioDataGridView.Rows.Count)
                newPosition = audioDataGridView.Rows.Count - audioDataGridView.DisplayedRowCount(false);
            audioDataGridView.FirstDisplayedScrollingRowIndex = newPosition;
            audioScrollBar.Position = (double)audioDataGridView.FirstDisplayedScrollingRowIndex /
                                      audioDataGridView.Rows.Count;
        }

        private static int getRowIndexByBoundedItem(DataGridView dataGrid, VkAudio item)
        {
            for (var i = 0; i < dataGrid.Rows.Count; i += 1)
            {
                var row = (VkAudio)dataGrid.Rows[i].DataBoundItem;
                if (row.Equals(item))
                    return i;
            }
            return -1;
        }

        private void AudioList_Load(object sender, EventArgs e)
        {
            setDataGridViewDoubleBuffered(audioDataGridView, true);
            audioScrollBar.Position = 0;
            bindData();
        }

        private void bindData()
        {
            audioDataGridView.Columns.Clear();
            audioDataGridView.AutoGenerateColumns = false;
            var col = new DataGridViewTextBoxColumn
            {
                DataPropertyName = "DisplayedName",
                Name = "displayedNameAudioDataGridViewColumn",
                HeaderText = Resources.MainForm_AudioArtistLabel,
                SortMode = DataGridViewColumnSortMode.Automatic
            };
            audioDataGridView.Columns.Add(col);
            audioDataGridView.DataSource = _audios;
        }

        private static void setDataGridViewDoubleBuffered(DataGridView dgv, bool setting)
        {
            var dgvType = dgv.GetType();
            var pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
            pi.SetValue(dgv, setting, null);
        }

        private void audioDataGridView_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (audioDataGridView.SelectedRows.Count < 1)
                return;
            var audio = audioDataGridView.SelectedRows[0].DataBoundItem as VkAudio;
            if (audio == null)
                return;
            if (AudioChangedByUser != null)
                AudioChangedByUser.Invoke(this, new AudioChangedByUserEventArgs(audio));
        }

        private void audioDataGridView_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
        {
            audioDataGridView.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Black;
        }

        private void audioDataGridView_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
        {
            audioDataGridView.Rows[e.RowIndex].DefaultCellStyle.BackColor = audioDataGridView.DefaultCellStyle.BackColor;
        }

        private void audioDataGridView_MouseEnter(object sender, EventArgs e)
        {
            var control = sender as Control;
            if (control == null)
                return;
            control.Focus();
        }

        private void AudioList_Resize(object sender, EventArgs e)
        {
            audioScrollBar.SliderSize = (double)audioDataGridView.DisplayedRowCount(true) / audioDataGridView.Rows.Count;
            audioScrollBar.Position = (double)audioDataGridView.FirstDisplayedScrollingRowIndex /
                                      audioDataGridView.Rows.Count;
        }

        private Point _lastPosition = new Point(0, 0);
        private void audioDataGridView_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Location.Equals(_lastPosition))
                return;
            audioScrollBar.AutoShow();
            _lastPosition = e.Location;
            audioScrollBar.StartAutoHide();
        }

        private void audioDataGridView_SelectionChanged(object sender, EventArgs e)
        {
            autosetScrollbarPosition();
        }

        private void autosetScrollbarPosition()
        {
            audioScrollBar.Position = (double)audioDataGridView.FirstDisplayedScrollingRowIndex /
                                      audioDataGridView.Rows.Count;
            audioScrollBar.AutoShow();
            audioScrollBar.StartAutoHide();
        }

        public void Remove(VkAudio item)
        {
            _audios.Remove(item);
            audioDataGridView.Refresh();
        }
    }
}
